﻿using System;
using System.Collections.Generic;
using mshtml;

namespace MQuery
{
    /// <summary>
    /// Filtering list of elements according to specific parameters.
    /// </summary>
    interface IFilter
    {
        /// <summary>
        /// Filters the specified list of elements according to the parameters
        /// </summary>
        /// <param name="parameters">The filter's parameters.</param>
        /// <param name="elements">The elements.</param>
        void Filter(string parameters, IList<IHTMLElement> elements);
    }

    /// <summary>
    /// List of elements filterint service
    /// </summary>
    static class Filters
    {
        private static EQFilter eqFilter = new EQFilter();
        private static FirstFilter firstFilter = new FirstFilter();

        /// <summary>
        ///  Filters the specified list of elements according to the filter string.
        /// </summary>
        /// <param name="filterString">The filter string.</param>
        /// <param name="elements">The elements.</param>
        public static void Filter(string filterString, IList<IHTMLElement> elements)
        {
            int index = filterString.IndexOf('(');
            string filterName = filterString;
            string filterParam = null;
            if (index != -1)
            {
                filterName = filterString.Substring(0, index);
                filterParam = filterString.Substring(index + 1, filterString.Length - index - 2);                               
            }
            IFilter filter = GetFilter(filterName); 
            filter.Filter(filterParam, elements);
        }

        /// <summary>
        /// Filters factory.
        /// </summary>
        /// <param name="filterName">Name of the filter.</param>
        /// <returns>Filter according to name</returns>
        private static IFilter GetFilter(string filterName)
        {
            switch (filterName)
            {
                case "eq":
                    {
                        return eqFilter;
                    }
                case "first":
                    {
                        return firstFilter;
                    }
                default:
                    {
                        throw new ArgumentOutOfRangeException("filterName", filterName);
                    }
            }
        }
    }

    /// <summary>
    /// Implement jQuery ":eq" filter 
    /// $(http://docs.jquery.com/Selectors/eq)
    /// </summary>
    class EQFilter: IFilter
    {
        #region IFilter Members

        /// <summary>
        /// Filters the specified list of elements according to the parameters
        /// </summary>
        /// <param name="parameters">The filter's parameters.</param>
        /// <param name="elements">The elements.</param>
        public virtual void Filter(string parameters, IList<IHTMLElement> elements)
        {
            Filter(int.Parse(parameters), elements);
        }

        /// <summary>
        /// Filters the specified index.
        /// </summary>
        /// <param name="index">The index.</param>
        /// <param name="elements">The elements.</param>
        protected void Filter(int index, IList<IHTMLElement> elements)
        {
            if (index > elements.Count)
            {
                elements.Clear();
            }
            else
            {
                IHTMLElement element = elements[index];
                elements.Clear();
                elements.Add(element);
                return;
            }
        }

        #endregion
    }

    /// <summary>
    /// Implement jQuery ":first" filter 
    /// $(http://docs.jquery.com/Selectors/first)
    /// </summary>
    class FirstFilter : EQFilter
    {
        #region IFilter Members
                /// <summary>
        /// Filters the specified list of elements according to the parameters
        /// </summary>
        /// <param name="parameters">The filter's parameters.</param>
        /// <param name="elements">The elements.</param>
        public override void Filter(string parameters, IList<IHTMLElement> elements)
        {
            base.Filter(0, elements);
        }

        #endregion
    }
}
